wayland: Don't round trip recursively during initialization
authorJonas Ådahl <jadahl@gmail.com>
Mon, 18 May 2015 08:02:45 +0000 (16:02 +0800)
committerJonas Ådahl <jadahl@gmail.com>
Wed, 20 May 2015 02:59:47 +0000 (10:59 +0800)
Instead use asynchronous round trips that is synchronized in the end of
the initialization. This makes it easier to track state, as we won't
dispatch arbitrary Wayland messages while processing globals.

https://bugzilla.gnome.org/show_bug.cgi?id=719819

gdk/wayland/gdkdisplay-wayland.c
gdk/wayland/gdkdisplay-wayland.h

index 6df25cff06b8255607a955fe34c8a69b3213842d..8e23afe96b12d031b96d78d49281b0f27a3c380b 100644 (file)
@@ -73,6 +73,35 @@ static void _gdk_wayland_display_load_cursor_theme (GdkWaylandDisplay *wayland_d
 
 G_DEFINE_TYPE (GdkWaylandDisplay, gdk_wayland_display, GDK_TYPE_DISPLAY)
 
+static void
+async_roundtrip_callback (void               *data,
+                          struct wl_callback *callback,
+                          uint32_t            time)
+{
+  GdkWaylandDisplay *display_wayland = data;
+
+  display_wayland->async_roundtrips =
+    g_list_remove (display_wayland->async_roundtrips, callback);
+  wl_callback_destroy (callback);
+}
+
+static const struct wl_callback_listener async_roundrip_listener = {
+  async_roundtrip_callback
+};
+
+static void
+_gdk_wayland_display_async_roundtrip (GdkWaylandDisplay *display_wayland)
+{
+  struct wl_callback *callback;
+
+  callback = wl_display_sync (display_wayland->wl_display);
+  wl_callback_add_listener (callback,
+                            &async_roundrip_listener,
+                            display_wayland);
+  display_wayland->async_roundtrips =
+    g_list_append (display_wayland->async_roundtrips, callback);
+}
+
 static void
 gdk_input_init (GdkDisplay *display)
 {
@@ -193,13 +222,13 @@ gdk_registry_handle_global (void               *data,
       output =
         wl_registry_bind (display_wayland->wl_registry, id, &wl_output_interface, MIN (version, 2));
       _gdk_wayland_screen_add_output (display_wayland->screen, id, output, MIN (version, 2));
-      wl_display_roundtrip (display_wayland->wl_display);
+      _gdk_wayland_display_async_roundtrip (display_wayland);
     }
   else if (strcmp (interface, "wl_seat") == 0)
     {
       seat = wl_registry_bind (display_wayland->wl_registry, id, &wl_seat_interface, MIN (version, 4));
       _gdk_wayland_device_manager_add_seat (gdk_display->device_manager, id, seat);
-      wl_display_roundtrip (display_wayland->wl_display);
+      _gdk_wayland_display_async_roundtrip (display_wayland);
     }
   else if (strcmp (interface, "wl_data_device_manager") == 0)
     {
@@ -273,8 +302,18 @@ _gdk_wayland_display_open (const gchar *display_name)
   display_wayland->wl_registry = wl_display_get_registry (display_wayland->wl_display);
   wl_registry_add_listener (display_wayland->wl_registry, &registry_listener, display_wayland);
 
-  /* Wait until the dust has settled during init... */
-  wl_display_roundtrip (display_wayland->wl_display);
+  _gdk_wayland_display_async_roundtrip (display_wayland);
+
+  /* Wait for initializing to complete. This means waiting for all
+   * asynchrounous roundtrips that were triggered during initial roundtrip. */
+  while (g_list_length (display_wayland->async_roundtrips) > 0)
+    {
+      if (wl_display_dispatch (display_wayland->wl_display) < 0)
+        {
+          g_object_unref (display);
+          return NULL;
+        }
+    }
 
   gdk_input_init (display);
 
@@ -308,6 +347,9 @@ gdk_wayland_display_dispose (GObject *object)
       display_wayland->selection = NULL;
     }
 
+  g_list_foreach (display_wayland->async_roundtrips,
+                  (GFunc) wl_callback_destroy, NULL);
+
   G_OBJECT_CLASS (gdk_wayland_display_parent_class)->dispose (object);
 }
 
index 781be518ef0b75dd59cf0a80e4d2bc047838a7b6..957a89a7748f9cb90147ee2cbca9231c26002a7c 100644 (file)
@@ -72,6 +72,8 @@ struct _GdkWaylandDisplay
   struct wl_data_device_manager *data_device_manager;
   struct wl_subcompositor *subcompositor;
 
+  GList *async_roundtrips;
+
   struct wl_cursor_theme *scaled_cursor_themes[GDK_WAYLAND_THEME_SCALES_COUNT];
   gchar *cursor_theme_name;
   int cursor_theme_size;